package controller.net;

import controller.exceptions.InvalidVersionException;
import controller.exceptions.ItemAlreadyRemovedException;
import filesystem.exceptions.InvalidModelItemException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.zip.*;
import model.*;

/**
 * Thread used for processing user's queries
 */
public class NetControllerServerThread extends Thread {

    private Socket clientSocket;
    private ObjectOutputStream out = null;
    private ObjectInputStream in = null;
    ModelHolder model = null;

    public NetControllerServerThread(Socket clientSocket, ModelHolder model) {
        this.model = model;
        this.clientSocket = clientSocket;
        try {
            out = new ObjectOutputStream(clientSocket.getOutputStream());
            in = new ObjectInputStream(clientSocket.getInputStream());
        } catch (IOException e) {
            //TODO
        }
    }

    @Override
    public void run() {
        try {
            String command = null;
            while (true) {
                //считываем команду
                command = (String) in.readObject();
                parseCommand(command);
            }
        } catch (IOException | ClassNotFoundException e) {
            //TODO
        }
    }

    private void parseCommand(String command) {
        ModelItem item = null;
        String modelType = null;
        ModelItem parametr = null;
        ArrayList items = null;
        int version = -1;
        switch (command) {
            case "SELECT":
                try {
                    modelType = (String) in.readObject();
                    parametr = (ModelItem) in.readObject();
                    if (parametr == null) {
                        items = model.getModel(modelType).selectItems();
                    } else {
                        items = model.getModel(modelType).selectItems(parametr);
                    }
                    //количество объектов
                    out.writeObject(items.size());
                    Iterator it = items.iterator();
                    while (it.hasNext()) {
                        item = (ModelItem) it.next();
                        out.writeObject(item);
                    }
                    out.writeObject("OK");
                } catch (Throwable e) {
                    int i = 0;
                    //TODO
                } finally {
                    break;
                }
            case "ADD":
                try {
                    modelType = (String) in.readObject();
                    item = (ModelItem) in.readObject();
                    model.getModel(modelType).addItem(item);
                    out.writeObject("OK");
                } catch (ClassNotFoundException e) {
                    //TODO
                } finally {
                    break;
                }
            case "EDIT":
                try {
                    modelType = (String) in.readObject();
                    item = (ModelItem) in.readObject();
                    try {
                        model.getModel(modelType).setItem(item);
                        out.writeObject("OK");
                    } catch (NullPointerException e) {
                        out.writeObject("ALREADY_REMOVED");
                        return;
                    } catch (InvalidVersionException e) {
                        out.writeObject("OLD_VERSION");
                        return;
                    } catch(ItemAlreadyRemovedException e) {
                        out.writeObject("ALREADY_REMOVED");
                        return;
                    }
                } catch (ClassNotFoundException e) {
                    //TODO
                } finally {
                    break;
                }
            case "REMOVE":
                try {
                    modelType = (String) in.readObject();
                    item = (ModelItem) in.readObject();
                    model.getModel(modelType).removeItem(item);
                    out.writeObject("OK");
                } catch (ClassNotFoundException e) {
                    //TODO
                } catch (NullPointerException e) {
                    out.writeObject("ALREADY_REMOVED");
                } finally {
                    break;
                }
            case "END":
                //завершаем прием
                try {
                    in.close();
                    out.close();
                    clientSocket.close();
                } catch (IOException e) {
                    //TODO
                } finally {
                    return;
                }
            default:
            //пришло что-то невнятное
            //TODO
        }
    }
}
